/* Soubor je ulozen v kodovani UTF-8.
 * Kontrola kódování: Příliš žluťoučký kůň úpěl ďábelské ódy. */

package cz.vse.adventura.po1715.xforv00_forejt.hra;

import cz.pecinovsky.english.pojj.adv_framework.game_txt.ICommand;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static cz.vse.adventura.po1715.xforv00_forejt.hra.Texty.*;





/*******************************************************************************
 * Instance třídy {@code APříkaz} představují rodičovskou třídu jednotlivých
 * příkazů
 *
 * @author    jméno autora
 * @version   0.00.000
 */
abstract class APříkaz implements ICommand
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================
    private static final String UVITANI = Texty.UVITANI;
    private static final String PRÁZDNÝ = "Zadal(a) jste prázdný příkaz.";
    private static final String NEZNÁMÝ = "Tento příkaz neznám." +
          "\nPro nápovědu zadejte příkaz \"?\"";
    private static final Map<String, ICommand> název2příkaz =
                                             new HashMap<String, ICommand>();

    private static final APříkaz
            příkazJDI = new PříkazJdi(),
            příkazKOUZLO = new PříkazKouzlo(),
            příkazOTEVŘI = new PříkazOtevři(),
            příkazZAVŘI = new PříkazZavři(),
            příkazVEZMI = new PříkazVezmi(),
            příkazPOLOŽ = new PříkazPolož(),
            příkazPŘEČTI = new PříkazPřečti(),
            příkazMLUV = new PříkazMluv(),
            příkazPODEJ = new PříkazPodej(),
            příkazVYPLŇ = new PříkazVyplň(),
            příkazKONEC = new PříkazKonec(),
            příkazHELP = new PříkazHelp();


//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
    private static boolean skončeno = true;


//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    private final String popis;
    private final String název;

//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================

    /***************************************************************************
     * Vrátí true, pokud je hra již ukončena.
     *
     * @return Požadovaná informace
     */
    static boolean isSkončeno()
     {
        return skončeno;
     }

    /***************************************************************************
     * Vrátí kolekci všech příkazů použitelných ve hře.
     *
     * @return Požadovaná kolekce
     */
//    @Override
    static Collection<? extends ICommand> getPříkazy()
     {
         return Collections.unmodifiableCollection(název2příkaz.values());
     }


//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

    /***************************************************************************
     * Zpracuje zadaný příkaz a vrátí text zprávy pro uživatele.
     *
     * @param příkaz Zadávaný příkaz
     * @return Textová odpověď hry na zadaný příkaz
     */
//    @Override
    static String zpracujPříkaz(String příkaz)
     {
        ICommand povel = null;
        String reakce = null;

        příkaz = příkaz.toLowerCase().trim();
        if(skončeno)
        {
            return doplň(začátek(příkaz));
        }
        if(příkaz.equals(""))
        {
            return doplň(PRÁZDNÝ);
        }
        if(Rozhovor.getStav()) {
            return doplň(Rozhovor.reaguj(příkaz));
        }
        String[] části = příkaz.split("\\s+");
        povel = název2příkaz.get(části[0]);
        if (povel == null) {
            return doplň(NEZNÁMÝ);                        //================>
        }
//        if (DBG.DEBUG < 0) {
//            povel.getParametry();
//        }

        String[] parametry = new String[části.length-1];
        System.arraycopy(části, 1, parametry, 0, parametry.length);

        reakce = povel.execute(parametry);
        reakce = doplň(reakce);
        return  reakce;
     }

  /***************************************************************************
     * Oznámení o ukončení hry.
     * Příští volání metody {@link #executeCommand(String)}
     * bude opět prvním voláním v nové hře.
     */
    static void konec() {
        skončeno = true;
    }

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     *
     */
    public APříkaz(String název, String popis)
    {
        this.název = název;
        this.popis = popis;
        název2příkaz.put(název.toLowerCase(), this);
    }



//== ABSTRAKTNÍ METODY =========================================================

    /***************************************************************************
     * Metoda realizující reakci hry na zadaní daného příkazu.
     * Počet parametru je závislý na konkrétním příkazu, např. příkazy Konec
     * a Nápověda nemají parametry, příkazy Jdi a Vezmi mají jeden parametr
     * příkaz Podlož muže mít dva parametry atd.
     *
     * @param parametry Parametry příkazu;
     *                  jejich počet muže byt pro každý příkaz jiný
     * @return Text zprávy vypsané po provedení příkazu
     */
    @Override
    public abstract String execute( String... parametry );

//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================

    /***************************************************************************
     * Vraci nazev prikazu, tj. text, ktery musi hrac zadat
     * pro vyvolani daneho prikazu
     *
     * @return Nazev prikazu
     */
    @Override
    public String getName()
    {
        return název;
    }


    /***************************************************************************
     * Vraci popis prikazu s vysvetlenim jeho funkce
     * a vyznamu jednotlivych parametru.
     *
     * @return Popis prikazu
     */
    @Override
    public String getDescription()
    {
        return popis;
    }

//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================

    /**************************************************************************
     * Vrátí uvítací hlášení a informace na začátku hry
     * @return výchozí informace
     */

    private static String začátek(String příkaz)
    {
        if(příkaz.equals("")) {
            Batoh.inicializuj();
            SprávceMístností.getSprávceMístností().inicializuj();
            skončeno = false;
            return UVITANI;             //=============================>
        } else {
            throw new IllegalStateException(
                                "Prvním příkazem není prázdný příkaz.");
        }

    }

    /***************************************************************************
     * Doplní reakci na příkaz o informace o aktuální místnosti a stavu batohu
     *
     * @param co se doplňuje
     * @return informace
     */

    private static String doplň(String reakce)
    {
        Hra hra = Hra.getHra();
        Místnost aktuální = hra.getActualPlace();
        StringBuilder sb = new StringBuilder(reakce);
        sb.append("\n------------------------------------------");
        sb.append(zMÍSTNOST).append(aktuální);
        sb.append(zSOUSEDÉ).append(aktuální.getNeighbors());
        sb.append(zPŘEDMĚTY).append(aktuální.getObjects());
        sb.append(zBATOH).append(Batoh.getBatoh().getObjects());
        return sb.toString();
    }

//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTY A METODA MAIN =======================================================
//
//     /***************************************************************************
//      * Testovací metoda.
//      */
//     public static void test()
//     {
//         APříkaz instance = new APříkaz();
//     }
//     /** @param args Parametry příkazového řádku - nepoužívané. */
//     public static void main(String[] args)  {  test();  }
}
